package com.runfast.pay.service.impl;

import com.runfast.paotui.service.OrderService;
import com.runfast.paotui.service.OrderStatusHistoryService;
import com.runfast.paotui.service.RefundService;
import com.runfast.pay.Channel;
import com.runfast.pay.service.WxpayService;
import com.runfast.pay.wxpay.WXPay;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: lijin
 * @date: 2018年04月02日
 */
@Service
@Slf4j
public class WxpayServiceImpl implements WxpayService {
    @Resource
    private WXPay wxAppPay;

    @Resource
    private WXPay wxPublicPay;

    @Resource
    private WXPay wxMiniPay;


    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderStatusHistoryService orderStatusHistoryService;

    @Autowired
    private RefundService refundService;


    @Override
    public Map<String, String> applyRefund(Channel channel, String orderNo, String refundNo, Integer payAmount, Integer refundAmount, String notifyUrl) {
        Validate.notNull(channel, "channel 不能为null");
        Validate.notBlank(orderNo);
        Validate.notBlank(refundNo);
        Validate.notNull(payAmount);
        Validate.notNull(refundAmount);
        if (payAmount < refundAmount) throw new RuntimeException("退款金额必须小于支付金额");


        HashMap<String, String> data = new HashMap<>();
        data.put("out_trade_no", orderNo);
        data.put("out_refund_no", refundNo);
        data.put("total_fee", payAmount.toString());
        data.put("refund_fee", refundAmount.toString());
        data.put("refund_fee_type", "CNY");
        data.put("notify_url", notifyUrl);


        try {

            Map<String, String> r = null;
            switch (channel) {
                case WXPAY_APP:
                    r = wxAppPay.refund(data);
                    break;
                case WXPAY_PUBLIC:
                    r = wxPublicPay.refund(data);
                    break;
                case WXPAY_MINI:
                    r = wxMiniPay.refund(data);
                    break;
            }
            return r;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Map<String, String> orderQuery(Channel channel, String orderNo) {
        Validate.notBlank(orderNo);

        HashMap<String, String> data = new HashMap<>();
        data.put("out_trade_no", orderNo);
        try {
            Map<String, String> r = null;
            switch (channel) {
                case WXPAY_APP:
                    r = wxAppPay.orderQuery(data);
                    break;
                case WXPAY_PUBLIC:
                    r = wxPublicPay.orderQuery(data);
                    break;
                case WXPAY_MINI:
                    r = wxMiniPay.orderQuery(data);
                    break;
            }
            return r;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }

    @Override
    public Map<String, String> refundrQuery(Channel channel, String refundNo) {
        Validate.notBlank(refundNo);

        HashMap<String, String> data = new HashMap<>();
        data.put("out_refund_no", refundNo);
        try {
            Map<String, String> r = null;
            switch (channel) {
                case WXPAY_APP:
                    r = wxAppPay.refundQuery(data);
                    break;
                case WXPAY_PUBLIC:
                    r = wxPublicPay.refundQuery(data);
                    break;
                case WXPAY_MINI:
                    r = wxMiniPay.refundQuery(data);
                    break;
            }
            return r;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }

    @Override
    public Map<String, String> closeOrder(Channel channel, String orderNo) {
        Validate.notBlank(orderNo);

        HashMap<String, String> data = new HashMap<String, String>();
        data.put("out_trade_no", orderNo);
        try {
            Map<String, String> r = null;
            switch (channel) {
                case WXPAY_APP:
                    r = wxAppPay.closeOrder(data);
                    break;
                case WXPAY_PUBLIC:
                    r = wxPublicPay.closeOrder(data);
                    break;
                case WXPAY_MINI:
                    r = wxMiniPay.closeOrder(data);
                    break;
            }
            return r;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }


    @Override
    public Map<String, String> prepay(Channel channel, String orderNo, String body, int payAmount, String clientIp, String notifyUrl,String openId) {
        Validate.notBlank(orderNo);
        Validate.notBlank(body);
        Validate.notBlank(clientIp);
        Validate.notBlank(notifyUrl);

        HashMap<String, String> data = new HashMap<String, String>();
        data.put("body", body);
        data.put("out_trade_no", orderNo);
        data.put("fee_type", "CNY");
        data.put("total_fee", payAmount + "");
        data.put("spbill_create_ip", clientIp);
        data.put("notify_url", notifyUrl);

        try {
            Map<String, String> r = null;
            switch (channel) {
                case WXPAY_APP:
                    data.put("trade_type", "APP");
                    r = wxAppPay.unifiedOrder(data);
                    break;
                case WXPAY_PUBLIC:

                    data.put("trade_type", "JSAPI");
                    data.put("openid", openId);
                    r = wxPublicPay.unifiedOrder(data);
                    break;
                case WXPAY_MINI:
                    data.put("trade_type", "JSAPI");
                    data.put("openid", openId);
                    r = wxMiniPay.unifiedOrder(data);
                    break;
            }
            return r;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }


}
